package com.videoweb.controller;

import com.videoweb.model.Video;
import com.videoweb.model.User;
import com.videoweb.service.VideoService;
import com.videoweb.service.UserService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.ResponseEntity;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.validation.constraints.NotBlank;
import javax.validation.constraints.Size;
import java.io.IOException;
import java.util.List;
import java.util.Map;
import java.nio.file.Files;
import java.io.File;
import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
import java.awt.Graphics2D;
import java.awt.Color;
import java.awt.Font;
import java.awt.FontMetrics;
import java.awt.RenderingHints;
import java.io.ByteArrayOutputStream;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.Executor;
import java.util.concurrent.Executors;

@RestController
@RequestMapping("/api/videos")
@CrossOrigin
@Validated
public class VideoController {
    private static final Logger log = LoggerFactory.getLogger(VideoController.class);
    
    private final VideoService videoService;
    private final UserService userService;
    
    // 异步执行器用于缩略图生成
    private final Executor thumbnailExecutor = Executors.newFixedThreadPool(2);
    
    public VideoController(VideoService videoService, UserService userService) {
        this.videoService = videoService;
        this.userService = userService;
    }
    
    @PostMapping("/upload")
    public ResponseEntity<?> uploadVideo(
            @RequestParam("file") MultipartFile file,
            @RequestParam @NotBlank(message = "Title is required") @Size(max = 100) String title,
            @RequestParam @Size(max = 500) String description) {
        try {
            log.info("Received video upload request - Title: {}, Description length: {}, File size: {}", 
                    title, description.length(), file.getSize());
            
            Authentication auth = SecurityContextHolder.getContext().getAuthentication();
            if (auth == null || !auth.isAuthenticated()) {
                log.warn("Unauthorized upload attempt");
                return ResponseEntity.status(401).body(Map.of("error", "Unauthorized"));
            }
            
            User user = userService.getCurrentUser(auth.getName())
                .orElseThrow(() -> new IllegalArgumentException("User not found"));
            Long userId = user.getId();
            log.info("User ID: {} attempting to upload video", userId);
            
            if (file.isEmpty()) {
                log.warn("Empty file received");
                return ResponseEntity.badRequest().body(Map.of("error", "File is empty"));
            }
            
            Video video = videoService.uploadVideo(file, title, description, userId);
            log.info("Video uploaded successfully - ID: {}, Title: {}", video.getId(), video.getTitle());
            
            // 异步生成缩略图，不阻塞响应
            CompletableFuture.runAsync(() -> {
                try {
                    String videoPath = "uploads/" + video.getFilePath();
                    String thumbnailPath = "uploads/thumbnails/" + video.getFilePath() + ".jpg";
                    
                    log.info("Starting async thumbnail generation for video: {}", video.getId());
                    boolean thumbnailGenerated = generateThumbnail(videoPath, thumbnailPath);
                    
                    if (thumbnailGenerated) {
                        log.info("Thumbnail generated successfully for video: {}", video.getId());
                    } else {
                        log.warn("Failed to generate thumbnail for video: {}, default thumbnail will be used", video.getId());
                    }
                } catch (Exception e) {
                    log.error("Error during async thumbnail generation for video {}: {}", video.getId(), e.getMessage());
                }
            }, thumbnailExecutor);
            
            return ResponseEntity.ok(Map.of(
                "id", video.getId(),
                "title", video.getTitle(),
                "message", "Video uploaded successfully"
            ));
        } catch (IllegalArgumentException e) {
            log.warn("Invalid upload request: {}", e.getMessage());
            return ResponseEntity.badRequest().body(Map.of("error", e.getMessage()));
        } catch (IOException e) {
            log.error("Failed to upload video", e);
            return ResponseEntity.internalServerError().body(Map.of("error", "Failed to upload video: " + e.getMessage()));
        } catch (Exception e) {
            log.error("Unexpected error during video upload", e);
            return ResponseEntity.internalServerError().body(Map.of("error", "An unexpected error occurred"));
        }
    }
    
    @GetMapping("/public")
    public ResponseEntity<List<Video>> getAllVideos() {
        return ResponseEntity.ok(videoService.getAllVideos());
    }
    
    @GetMapping("/user")
    public ResponseEntity<List<Video>> getUserVideos() {
        Authentication auth = SecurityContextHolder.getContext().getAuthentication();
        User user = userService.getCurrentUser(auth.getName())
            .orElseThrow(() -> new IllegalArgumentException("User not found"));
        Long userId = user.getId();
        return ResponseEntity.ok(videoService.getUserVideos(userId));
    }
    
    @GetMapping("/{id}")
    public ResponseEntity<Video> getVideo(@PathVariable Long id) {
        return videoService.getVideoById(id)
                .map(ResponseEntity::ok)
                .orElseGet(() -> ResponseEntity.notFound().build());
    }
    
    @DeleteMapping("/{id}")
    public ResponseEntity<?> deleteVideo(@PathVariable Long id) {
        Authentication auth = SecurityContextHolder.getContext().getAuthentication();
        User user = userService.getCurrentUser(auth.getName())
            .orElseThrow(() -> new IllegalArgumentException("User not found"));
        Long userId = user.getId();
        boolean deleted = videoService.deleteVideo(id, userId);
        if (deleted) {
            return ResponseEntity.ok().build();
        }
        return ResponseEntity.notFound().build();
    }
    
    @GetMapping("/{id}/thumbnail")
    public ResponseEntity<?> getVideoThumbnail(@PathVariable Long id) {
        try {
            // 获取视频信息
            Video video = videoService.getVideoById(id).orElse(null);
            if (video == null) {
                log.warn("Video not found for thumbnail generation: {}", id);
                return ResponseEntity.notFound().build();
            }

            // 设置路径
            String videoPath = "uploads/" + video.getFilePath();
            String thumbnailDir = "uploads/thumbnails/";
            String thumbnailPath = thumbnailDir + video.getFilePath() + ".jpg";

            File videoFile = new File(videoPath);
            if (!videoFile.exists()) {
                log.error("Video file not found: {}", videoPath);
                return ResponseEntity.notFound().build();
            }

            File thumbnailFile = new File(thumbnailPath);
            if (!thumbnailFile.exists()) {
                log.info("Generating thumbnail for video: {}", id);
                
                // 确保缩略图目录存在
                File dir = new File(thumbnailDir);
                if (!dir.exists() && !dir.mkdirs()) {
                    log.error("Failed to create thumbnail directory: {}", thumbnailDir);
                    return ResponseEntity.internalServerError().body("Failed to create thumbnail directory");
                }

                if (!generateThumbnail(videoPath, thumbnailPath)) {
                    log.warn("Failed to generate thumbnail for video: {}, returning default", id);
                    return getDefaultThumbnail();
                }
            }

            // 读取并返回缩略图
            try {
                byte[] imageBytes = Files.readAllBytes(thumbnailFile.toPath());
                return ResponseEntity.ok()
                        .header("Content-Type", "image/jpeg")
                        .header("Cache-Control", "max-age=86400") // 缓存24小时
                        .body(imageBytes);
            } catch (IOException e) {
                log.error("Error reading thumbnail file for video {}: {}", id, e.getMessage());
                return getDefaultThumbnail();
            }
        } catch (Exception e) {
            log.error("Unexpected error in thumbnail generation for video {}: {}", id, e.getMessage());
            return getDefaultThumbnail();
        }
    }

    // FFmpeg路径缓存
    private String ffmpegPath = null;
    
    /**
     * 获取FFmpeg路径
     */
    private String getFFmpegPath() {
        if (ffmpegPath != null) {
            return ffmpegPath;
        }
        
        String[] ffmpegPaths = {
            "ffmpeg", // 系统PATH中的ffmpeg
            "C:\\Users\\camphora\\AppData\\Local\\Microsoft\\WinGet\\Packages\\Gyan.FFmpeg_Microsoft.Winget.Source_8wekyb3d8bbwe\\ffmpeg-7.1.1-full_build\\bin\\ffmpeg.exe",
            "C:\\ffmpeg\\bin\\ffmpeg.exe",
            "ffmpeg.exe"
        };
        
        for (String path : ffmpegPaths) {
            try {
                ProcessBuilder pb = new ProcessBuilder(path, "-version");
                pb.redirectErrorStream(true);
                Process process = pb.start();
                boolean finished = process.waitFor(5, java.util.concurrent.TimeUnit.SECONDS);
                if (finished && process.exitValue() == 0) {
                    log.info("FFmpeg found at: {}", path);
                    ffmpegPath = path;
                    return path;
                }
            } catch (Exception e) {
                log.debug("FFmpeg not found at: {}", path);
            }
        }
        log.warn("FFmpeg not available in any of the checked paths");
        return null;
    }
    
    /**
     * 检查FFmpeg是否可用
     */
    private boolean isFFmpegAvailable() {
        return getFFmpegPath() != null;
    }
    
    /**
     * 生成视频缩略图
     */
    private boolean generateThumbnail(String videoPath, String thumbnailPath) {
        String ffmpeg = getFFmpegPath();
        if (ffmpeg == null) {
            log.warn("FFmpeg not available, cannot generate thumbnail");
            return false;
        }
        
        try {
            // 使用绝对路径
            File videoFile = new File(videoPath);
            File thumbnailFile = new File(thumbnailPath);
            
            String absoluteVideoPath = videoFile.getAbsolutePath();
            String absoluteThumbnailPath = thumbnailFile.getAbsolutePath();
            
            log.info("Using absolute paths - Video: {}, Thumbnail: {}", absoluteVideoPath, absoluteThumbnailPath);
            
            if (!videoFile.exists()) {
                log.error("Video file not found: {}", absoluteVideoPath);
                return false;
            }
            
            // 确保缩略图目录存在
            File thumbnailDir = thumbnailFile.getParentFile();
            if (!thumbnailDir.exists()) {
                boolean created = thumbnailDir.mkdirs();
                log.info("Created thumbnail directory: {} - success: {}", thumbnailDir.getAbsolutePath(), created);
                if (!created) {
                    log.error("Failed to create thumbnail directory: {}", thumbnailDir.getAbsolutePath());
                    return false;
                }
            }
            
            log.info("Thumbnail directory ready - exists: {}, writable: {}", 
                thumbnailDir.exists(), thumbnailDir.canWrite());
            
            // 使用简化的ffmpeg命令，添加更多选项来优化处理速度
            ProcessBuilder pb = new ProcessBuilder(
                ffmpeg,
                "-i", absoluteVideoPath,
                "-ss", "00:00:01",  // 从第1秒开始截取，避免黑屏
                "-vframes", "1",
                "-q:v", "2",        // 高质量
                "-f", "image2",
                "-y",               // 覆盖已存在的文件
                absoluteThumbnailPath
            );
            
            // 设置工作目录和环境
            pb.directory(new File(System.getProperty("user.dir")));
            pb.redirectErrorStream(false); // 分别处理stdout和stderr
            
            log.info("FFmpeg command: {}", String.join(" ", pb.command()));
            log.info("Video file info - exists: {}, size: {} bytes, readable: {}", 
                videoFile.exists(), videoFile.length(), videoFile.canRead());
            
            Process process = pb.start();
            
            // 实时读取输出，避免缓冲区阻塞
            StringBuilder output = new StringBuilder();
            StringBuilder error = new StringBuilder();
            
            Thread outputReader = new Thread(() -> {
                try (java.io.BufferedReader reader = new java.io.BufferedReader(
                        new java.io.InputStreamReader(process.getInputStream()))) {
                    String line;
                    while ((line = reader.readLine()) != null) {
                        output.append(line).append("\n");
                        log.debug("FFmpeg stdout: {}", line);
                    }
                } catch (IOException e) {
                    log.warn("Error reading FFmpeg stdout: {}", e.getMessage());
                }
            });
            
            Thread errorReader = new Thread(() -> {
                try (java.io.BufferedReader reader = new java.io.BufferedReader(
                        new java.io.InputStreamReader(process.getErrorStream()))) {
                    String line;
                    while ((line = reader.readLine()) != null) {
                        error.append(line).append("\n");
                        log.debug("FFmpeg stderr: {}", line);
                    }
                } catch (IOException e) {
                    log.warn("Error reading FFmpeg stderr: {}", e.getMessage());
                }
            });
            
            outputReader.start();
            errorReader.start();
            
            // 等待进程完成，增加超时时间到60秒
            boolean finished = process.waitFor(60, java.util.concurrent.TimeUnit.SECONDS);
            
            if (!finished) {
                log.error("FFmpeg process timed out after 60 seconds for video: {}", absoluteVideoPath);
                process.destroyForcibly();
                
                // 等待读取线程完成
                try {
                    outputReader.join(1000);
                    errorReader.join(1000);
                } catch (InterruptedException e) {
                    Thread.currentThread().interrupt();
                }
                
                return false;
            }
            
            // 等待读取线程完成
            try {
                outputReader.join(5000);
                errorReader.join(5000);
            } catch (InterruptedException e) {
                Thread.currentThread().interrupt();
            }
            
            int exitCode = process.exitValue();
            log.info("FFmpeg process completed with exit code: {}", exitCode);
            log.info("FFmpeg stdout: {}", output.toString());
            log.info("FFmpeg stderr: {}", error.toString());

            if (exitCode != 0) {
                log.error("FFmpeg failed with exit code {} for video: {}", exitCode, absoluteVideoPath);
                return false;
            }
            
            // 验证缩略图文件是否生成
            boolean fileExists = thumbnailFile.exists();
            long fileSize = fileExists ? thumbnailFile.length() : 0;
            
            log.info("Thumbnail generation result - file exists: {}, size: {} bytes", fileExists, fileSize);
            
            if (fileExists && fileSize > 0) {
                log.info("Thumbnail generated successfully: {}, size: {} bytes", absoluteThumbnailPath, fileSize);
                return true;
            } else {
                log.error("Thumbnail file not created or empty - path: {}", absoluteThumbnailPath);
                
                // 列出缩略图目录的内容以便调试
                if (thumbnailDir.exists()) {
                    String[] files = thumbnailDir.list();
                    log.info("Files in thumbnail directory: {}", files != null ? java.util.Arrays.toString(files) : "null");
                }
                
                return false;
            }
        } catch (Exception e) {
            log.error("Error during thumbnail generation for video {}: {}", videoPath, e.getMessage(), e);
            return false;
        }
    }

    /**
     * 返回默认缩略图
     */
    private ResponseEntity<?> getDefaultThumbnail() {
        try {
            // 创建一个简单的默认缩略图 (480x360 灰色背景，带有播放图标)
            java.awt.image.BufferedImage image = new java.awt.image.BufferedImage(480, 360, java.awt.image.BufferedImage.TYPE_INT_RGB);
            java.awt.Graphics2D g2d = image.createGraphics();
            
            // 设置背景色
            g2d.setColor(java.awt.Color.GRAY);
            g2d.fillRect(0, 0, 480, 360);
            
            // 绘制播放按钮
            g2d.setColor(java.awt.Color.WHITE);
            g2d.setRenderingHint(java.awt.RenderingHints.KEY_ANTIALIASING, java.awt.RenderingHints.VALUE_ANTIALIAS_ON);
            
            // 播放按钮三角形
            int centerX = 240;
            int centerY = 180;
            int[] xPoints = {centerX - 30, centerX - 30, centerX + 30};
            int[] yPoints = {centerY - 25, centerY + 25, centerY};
            g2d.fillPolygon(xPoints, yPoints, 3);
            
            // 添加文字
            g2d.setFont(new java.awt.Font("Arial", java.awt.Font.BOLD, 24));
            java.awt.FontMetrics fm = g2d.getFontMetrics();
            String text = "Video Thumbnail";
            int textX = (480 - fm.stringWidth(text)) / 2;
            g2d.drawString(text, textX, 280);
            
            g2d.dispose();
            
            // 转换为字节数组
            java.io.ByteArrayOutputStream baos = new java.io.ByteArrayOutputStream();
            javax.imageio.ImageIO.write(image, "jpg", baos);
            byte[] imageBytes = baos.toByteArray();
            
            return ResponseEntity.ok()
                    .header("Content-Type", "image/jpeg")
                    .header("Cache-Control", "max-age=3600") // 缓存1小时
                    .body(imageBytes);
        } catch (Exception e) {
            log.error("Failed to generate default thumbnail", e);
            return ResponseEntity.internalServerError()
                    .body(Map.of("error", "Failed to generate thumbnail", "message", "FFmpeg not available and default thumbnail generation failed"));
        }
    }
}
